// 判断是否为Node.js环境
const isNode = typeof process!== 'undefined' && process.versions && process.versions.node;

// 根据环境创建不同的console对象（用于在Node.js环境下模拟浏览器的console）
let consoleObj;
if (isNode) {
    consoleObj = {
        log: console.log.bind(console),
        debug: console.debug.bind(console),
        info: console.info.bind(console),
        error: console.error.bind(console)
    };
} else {
    consoleObj = console;
}

// 创建一个自执行函数，形成闭包环境
const ConsoleLogger = (function () {
    // 定义日志级别常量
    const LOG_LEVEL_DEBUG = 1;
    const LOG_LEVEL_INFO = 2;
    const LOG_LEVEL_ERROR = 3;

    // 存储单例实例的私有变量
    let instance;

    // 当前日志级别，默认为INFO级别
    let currentLogLevel = LOG_LEVEL_INFO;

    // 存储外部注入的日志对象
    let externalLogger;

    // 当前要使用的标签
    let currentTag = "";

    // 构造函数
    function ConsoleLogger(enabled = true, tag = "") {
        this.enabled = enabled;
        this.tag = tag;
        // 在实例上添加一个属性来存储闭包内的方法引用
        this.methods = {
            getInstance: getInstance,
            setLogLevel: setLogLevel,
            log: log,
            debug: debug,
            info: info,
            error: error,
            setTag: setTag,
            setEnabled: setEnabled,
            injectExternalLogger: injectExternalExternalLogger
        };
    }

    // 获取单例实例的函数
    function getInstance(enabled = true, tag = "") {
        if (!instance) {
            instance = new ConsoleLogger(enabled, tag);
        }
        return instance;
    }

    // 设置日志级别的函数
    function setLogLevel(logLevel) {
        currentLogLevel = logLevel;
    }

    // 检查是否应该输出日志（根据当前日志级别）的函数
    function shouldLog(logLevel) {
        return logLevel >= currentLogLevel;
    }

    // 通用的日志输出函数，可根据是否注入外部日志对象选择 输出方式
    function logMessage(logLevel, method,...message) {
        const logger = getInstance();
        // console.log("logMessage",logger.enabled,"s:",shouldLog(logLevel));
        // console.log("logMessage","logLevel:",logLevel,"currentLogLevel:",currentLogLevel);
        if (logger.enabled && shouldLog(logLevel)) {
            if (externalLogger) {
                // 使用注入的外部日志对象进行输出
                externalLogger[method](logger.tag,...message);
            } else {
                // 使用默认的console对象进行输出
                consoleObj[method](logger.tag,...message);
            }
        }
    }

    // 具体的日志方法
    function log(...message) {
        logMessage(LOG_LEVEL_INFO, 'log',currentTag,...message);
    }

    function debug(...message) {
        logMessage(LOG_LEVEL_DEBUG, 'debug',currentTag,...message);
    }

    function info(...message) {
        logMessage(LOG_LEVEL_INFO, 'info',currentTag,...message);
    }

    function error(...message) {
        logMessage(LOG_LEVEL_ERROR, 'error',currentTag,...message);
    }

    // 设置标签的函数
    function setTag(tag) {
        const logger = getInstance();
        logger.tag = tag;
    }

    // 设置是否启用日志的函数
    function setEnabled(enabled) {
        const logger = getInstance();
        logger.enabled = enabled;
    }

    // 注入外部日志对象的函数
    function injectExternalExternalLogger(externalLogger) {
        this.externalLogger = externalLogger;
    }

    // 动态设置当前要使用的标签的函数
    function setCurrentTag(tag) {
        currentTag = tag;
    }

    // 将日志级别常量挂载到ConsoleLogger函数上，以便在闭包外部访问
    ConsoleLogger.LOG_LEVEL_DEBUG = LOG_LEVEL_DEBUG;
    ConsoleLogger.LOG_LEVEL_INFO = LOG_LEVEL_INFO;
    ConsoleLogger.LOG_LEVEL_ERROR = LOG_LEVEL_ERROR;

    // 给ConsoleLogger函数添加属性，使其能访问闭包内的方法
    ConsoleLogger.getInstance = getInstance;
    ConsoleLogger.setLogLevel = setLogLevel;
    ConsoleLogger.log = log;
    ConsoleLogger.debug = debug;
    ConsoleLogger.info = info;
    ConsoleLogger.error = error;
    ConsoleLogger.setTag = setTag;
    ConsoleLogger.setEnabled = setEnabled;
    ConsoleLogger.injectExternalLogger = injectExternalExternalLogger;
    ConsoleLogger.setCurrentTag = setCurrentTag;

    // 返回 ConsoleLogger构造函数作为唯一的对外暴露接口，
    // 通过闭包内部维护的状态来实现日志功能
    return ConsoleLogger;
})();

// 示例用法：

// 自定义一个简单的日志对象（这里只是示例，实际可根据需求定制更复杂的日志对象）
const customLogger = {
    log: function (tag,...message) {
        consoleObj.log(`[${tag}]`,...message);
    },
    debug: function (tag,...message) {
        consoleObj.debug(`[${tag}]`,...message);
    },
    info: function (tag,...message) {
        consoleObj.info(`[${tag}]`,...message);
    },
    error: function (tag,...message) {
        consoleObj.error(`[${tag}]`,...message);
    }
};

// 注入外部日志对象
ConsoleLogger.injectExternalLogger(customLogger);


// 设置日志级别为DEBUG
ConsoleLogger.setLogLevel(ConsoleLogger.LOG_LEVEL_DEBUG);
// 获取日志实例并设置标签
const logger = ConsoleLogger.getInstance();
// 通过实例上的methods属性来调用setTag方法
logger.methods.setTag("MyAppLogger");


ConsoleLogger.setCurrentTag("方法1");
// 输出不同级别的日志
ConsoleLogger.log("这是一条LOG日志");
ConsoleLogger.debug("这是一条DEBUG日志");
ConsoleLogger.info("这是一条INFO日志");
ConsoleLogger.error("这是一条ERROR日志");
